பைத்தானின் மல்டிபிராசசிங் மாட்யூலுக்கான ஒரு விரிவான வழிகாட்டி. இது இணைச் செயலாக்கத்திற்கான பிராசஸ் பூல்கள் மற்றும் திறமையான தரவுப் பகிர்வுக்கான பகிரப்பட்ட நினைவக மேலாண்மையில் கவனம் செலுத்துகிறது. உங்கள் பைத்தான் பயன்பாடுகளை செயல்திறன் மற்றும் அளவிடுதலுக்காக மேம்படுத்துங்கள்.
பைத்தான் மல்டிபிராசசிங்: பிராசஸ் பூல்கள் மற்றும் பகிரப்பட்ட நினைவகத்தில் தேர்ச்சி பெறுதல்
பைத்தான், அதன் நேர்த்தி மற்றும் பன்முகத்தன்மை இருந்தபோதிலும், குளோபல் இன்டர்பிரெட்டர் லாக் (GIL) காரணமாக செயல்திறன் சிக்கல்களை அடிக்கடி எதிர்கொள்கிறது. GIL எந்த நேரத்திலும் ஒரு த்ரெட் மட்டுமே பைத்தான் இன்டர்பிரெட்டரின் கட்டுப்பாட்டைக் கொண்டிருக்க அனுமதிக்கிறது. இந்த வரம்பு CPU-சார்ந்த பணிகளை கணிசமாகப் பாதிக்கிறது, மல்டித்ரெட் பயன்பாடுகளில் உண்மையான இணைச் செயலாக்கத்தைத் தடுக்கிறது. இந்தச் சவாலைச் சமாளிக்க, பைத்தானின் multiprocessing மாட்யூல் பல பிராசஸ்களைப் பயன்படுத்துவதன் மூலம் ஒரு சக்திவாய்ந்த தீர்வை வழங்குகிறது, இது GIL-ஐத் தவிர்த்து உண்மையான இணைச் செயலாக்கத்தை செயல்படுத்துகிறது.
இந்த விரிவான வழிகாட்டி, பைத்தான் மல்டிபிராசசிங்கின் முக்கியக் கருத்துக்களை, குறிப்பாக பிராசஸ் பூல்கள் மற்றும் பகிரப்பட்ட நினைவக மேலாண்மையில் கவனம் செலுத்தி ஆராய்கிறது. பிராசஸ் பூல்கள் இணைப் பணிகளைச் செயல்படுத்துவதை எவ்வாறு நெறிப்படுத்துகின்றன மற்றும் பகிரப்பட்ட நினைவகம் பிராசஸ்களுக்கு இடையில் திறமையான தரவுப் பகிர்வுக்கு எவ்வாறு உதவுகிறது என்பதை நாம் ஆராய்வோம், உங்கள் மல்டி-கோர் பிராசசர்களின் முழு திறனையும் வெளிக்கொணர்வோம். சிறந்த நடைமுறைகள், பொதுவான சிக்கல்கள் மற்றும் உங்கள் பைத்தான் பயன்பாடுகளை செயல்திறன் மற்றும் அளவிடுதலுக்காக மேம்படுத்துவதற்கான அறிவு மற்றும் திறன்களை உங்களுக்கு வழங்க நடைமுறை உதாரணங்களை வழங்குவோம்.
மல்டிபிராசசிங்கின் தேவையைப் புரிந்துகொள்ளுதல்
தொழில்நுட்ப விவரங்களுக்குள் செல்வதற்கு முன், சில சூழ்நிலைகளில் மல்டிபிராசசிங் ஏன் அவசியம் என்பதைப் புரிந்துகொள்வது முக்கியம். பின்வரும் சூழ்நிலைகளைக் கவனியுங்கள்:
- CPU-சார்ந்த பணிகள்: இமேஜ் பிராசசிங், எண் கணிதக் கணக்கீடுகள் அல்லது சிக்கலான சிமுலேஷன்கள் போன்ற CPU பிராசசிங்கை பெரிதும் நம்பியிருக்கும் செயல்பாடுகள், GIL-ஆல் கடுமையாகக் கட்டுப்படுத்தப்படுகின்றன. மல்டிபிராசசிங் இந்தப் பணிகளை பல கோர்களில் விநியோகிக்க அனுமதிக்கிறது, இதனால் குறிப்பிடத்தக்க வேகத்தை அடைகிறது.
- பெரிய தரவுத்தொகுப்புகள்: பெரிய தரவுத்தொகுப்புகளைக் கையாளும் போது, பிராசசிங் பணிச்சுமையை பல பிராசஸ்களில் விநியோகிப்பது பிராசசிங் நேரத்தை வியத்தகு முறையில் குறைக்கும். பங்குச் சந்தைத் தரவு அல்லது மரபணு வரிசைகளை பகுப்பாய்வு செய்வதை கற்பனை செய்து பாருங்கள் - மல்டிபிராசசிங் இந்தப் பணிகளை நிர்வகிக்கக்கூடியதாக மாற்றும்.
- சுதந்திரமான பணிகள்: உங்கள் பயன்பாட்டில் பல சுதந்திரமான பணிகளை ஒரே நேரத்தில் இயக்குவது அடங்கியிருந்தால், மல்டிபிராசசிங் அவற்றை இணைச் செயலாக்கம் செய்ய ஒரு இயல்பான மற்றும் திறமையான வழியை வழங்குகிறது. ஒரே நேரத்தில் பல வாடிக்கையாளர் கோரிக்கைகளைக் கையாளும் ஒரு வலை சேவையகம் அல்லது இணையாக வெவ்வேறு தரவு மூலங்களைப் பிராசஸ் செய்யும் ஒரு தரவுக் குழாயைப் பற்றி சிந்தியுங்கள்.
இருப்பினும், மல்டிபிராசசிங் அதன் சொந்த சிக்கல்களை அறிமுகப்படுத்துகிறது என்பதைக் கவனத்தில் கொள்ள வேண்டும், அதாவது இன்டர்-பிராசஸ் கம்யூனிகேஷன் (IPC) மற்றும் நினைவக மேலாண்மை போன்றவை. மல்டிபிராசசிங் மற்றும் மல்டித்ரெட்டிங் இடையே தேர்ந்தெடுப்பது கையில் உள்ள பணியின் தன்மையைப் பெரிதும் சார்ந்துள்ளது. I/O-சார்ந்த பணிகள் (எ.கா., நெட்வொர்க் கோரிக்கைகள், டிஸ்க் I/O) பெரும்பாலும் asyncio போன்ற லைப்ரரிகளைப் பயன்படுத்தி மல்டித்ரெட்டிங்கிலிருந்து அதிகப் பயனடைகின்றன, அதே நேரத்தில் CPU-சார்ந்த பணிகள் பொதுவாக மல்டிபிராசசிங்கிற்கு மிகவும் பொருத்தமானவை.
பிராசஸ் பூல்களை அறிமுகப்படுத்துதல்
ஒரு பிராசஸ் பூல் என்பது ஒரே நேரத்தில் பணிகளைச் செயல்படுத்தக் கிடைக்கும் வொர்க்கர் பிராசஸ்களின் தொகுப்பாகும். multiprocessing.Pool கிளாஸ் இந்த வொர்க்கர் பிராசஸ்களை நிர்வகிக்கவும், அவற்றுக்கிடையே பணிகளை விநியோகிக்கவும் ஒரு வசதியான வழியை வழங்குகிறது. பிராசஸ் பூல்களைப் பயன்படுத்துவது, தனிப்பட்ட பிராசஸ்களை கைமுறையாக நிர்வகிக்கத் தேவையில்லாமல் பணிகளை இணைச் செயலாக்கம் செய்வதை எளிதாக்குகிறது.
ஒரு பிராசஸ் பூலை உருவாக்குதல்
ஒரு பிராசஸ் பூலை உருவாக்க, நீங்கள் பொதுவாக உருவாக்க வேண்டிய வொர்க்கர் பிராசஸ்களின் எண்ணிக்கையைக் குறிப்பிடுவீர்கள். எண்ணிக்கை குறிப்பிடப்படவில்லை என்றால், கணினியில் உள்ள CPU-களின் எண்ணிக்கையைத் தீர்மானிக்க multiprocessing.cpu_count() பயன்படுத்தப்பட்டு, அவ்வளவு பிராசஸ்களுடன் ஒரு பூல் உருவாக்கப்படுகிறது.
from multiprocessing import Pool, cpu_count
def worker_function(x):
# Perform some computationally intensive task
return x * x
if __name__ == '__main__':
num_processes = cpu_count() # Get the number of CPUs
with Pool(processes=num_processes) as pool:
results = pool.map(worker_function, range(10))
print(results)
விளக்கம்:
multiprocessingமாட்யூலிலிருந்துPoolகிளாஸ் மற்றும்cpu_countஃபங்ஷனை நாம் இம்போர்ட் செய்கிறோம்.- ஒரு கணக்கீட்டு ரீதியாகத் தீவிரமான பணியைச் செய்யும் (இந்த வழக்கில், ஒரு எண்ணை வர்க்கப்படுத்துதல்)
worker_function-ஐ நாம் வரையறுக்கிறோம். if __name__ == '__main__':பிளாக்கின் உள்ளே (ஸ்கிரிப்ட் நேரடியாக இயக்கப்படும்போது மட்டுமே குறியீடு செயல்படுத்தப்படுவதை உறுதி செய்கிறது),with Pool(...) as pool:ஸ்டேட்மென்டைப் பயன்படுத்தி ஒரு பிராசஸ் பூலை உருவாக்குகிறோம். இது பிளாக்கிலிருந்து வெளியேறும்போது பூல் சரியாக நிறுத்தப்படுவதை உறுதி செய்கிறது.range(10)இல் உள்ள ஒவ்வொரு உறுப்பிற்கும்worker_function-ஐப் பயன்படுத்தpool.map()மெத்தடைப் பயன்படுத்துகிறோம்.map()மெத்தட் பூலில் உள்ள வொர்க்கர் பிராசஸ்களுக்கு இடையில் பணிகளை விநியோகித்து, முடிவுகளின் பட்டியலைத் தருகிறது.- இறுதியாக, முடிவுகளை நாம் அச்சிடுகிறோம்.
`map()`, `apply()`, `apply_async()`, மற்றும் `imap()` மெத்தடுகள்
Pool கிளாஸ் வொர்க்கர் பிராசஸ்களுக்கு பணிகளைச் சமர்ப்பிக்க பல மெத்தடுகளை வழங்குகிறது:
map(func, iterable):iterableஇல் உள்ள ஒவ்வொரு உருப்படிக்கும்func-ஐப் பயன்படுத்துகிறது, எல்லா முடிவுகளும் தயாராகும் வரை காத்திருக்கும். முடிவுகள் உள்ளீட்டு iterable-இன் அதே வரிசையில் ஒரு பட்டியலில் திருப்பித் தரப்படும்.apply(func, args=(), kwds={}): கொடுக்கப்பட்ட ஆர்கியூமென்ட்களுடன்func-ஐ அழைக்கிறது. ஃபங்ஷன் முடியும் வரை இது காத்திருந்து முடிவைத் தருகிறது. பொதுவாக, பல பணிகளுக்குmap-ஐ விடapplyகுறைவான செயல்திறன் கொண்டது.apply_async(func, args=(), kwds={}, callback=None, error_callback=None):apply-இன் நான்-பிளாக்கிங் பதிப்பு. இது ஒருAsyncResultஆப்ஜெக்டைத் தருகிறது. முடிவைப் பெற, நீங்கள்AsyncResultஆப்ஜெக்ட்டின்get()மெத்தடைப் பயன்படுத்தலாம், இது முடிவு கிடைக்கும் வரை காத்திருக்கும். இது கால்பேக் ஃபங்ஷன்களையும் ஆதரிக்கிறது, இது முடிவுகளை அசிங்க்ரோனஸாகச் செயல்படுத்த உங்களை அனுமதிக்கிறது. ஃபங்ஷனால் ஏற்படும் விதிவிலக்குகளைக் கையாளerror_callback-ஐப் பயன்படுத்தலாம்.imap(func, iterable, chunksize=1):map-இன் ஒரு சோம்பேறி பதிப்பு. இது ஒரு இட்டரேட்டரைத் தருகிறது, அது முடிவுகள் கிடைக்கும்போது அவற்றை அளிக்கிறது, எல்லாப் பணிகளும் முடியும் வரை காத்திருக்காது.chunksizeஆர்கியூமென்ட் ஒவ்வொரு வொர்க்கர் பிராசஸிற்கும் சமர்ப்பிக்கப்படும் வேலைத் துண்டுகளின் அளவைக் குறிப்பிடுகிறது.imap_unordered(func, iterable, chunksize=1):imap-ஐப் போன்றது, ஆனால் முடிவுகளின் வரிசை உள்ளீட்டு iterable-இன் வரிசையுடன் பொருந்தும் என்பதற்கு உத்தரவாதம் இல்லை. முடிவுகளின் வரிசை முக்கியமில்லை என்றால் இது மிகவும் செயல்திறன் மிக்கதாக இருக்கும்.
சரியான மெத்தடைத் தேர்ந்தெடுப்பது உங்கள் குறிப்பிட்ட தேவைகளைப் பொறுத்தது:
- முடிவுகள் உள்ளீட்டு iterable-இன் அதே வரிசையில் தேவைப்படும்போது மற்றும் எல்லாப் பணிகளும் முடியும் வரை காத்திருக்கத் தயாராக இருக்கும்போது
map-ஐப் பயன்படுத்தவும். - ஒற்றைப் பணிகளுக்கு அல்லது நீங்கள் கீவேர்டு ஆர்கியூமென்ட்களை அனுப்ப வேண்டியிருக்கும் போது
apply-ஐப் பயன்படுத்தவும். - நீங்கள் பணிகளை அசிங்க்ரோனஸாக இயக்க வேண்டும் மற்றும் முக்கிய பிராசஸை பிளாக் செய்ய விரும்பாதபோது
apply_async-ஐப் பயன்படுத்தவும். - முடிவுகள் கிடைக்கும்போது அவற்றைச் செயல்படுத்த வேண்டும் மற்றும் ஒரு சிறிய ஓவர்ஹெட்டைத் தாங்கிக்கொள்ள முடியும் போது
imap-ஐப் பயன்படுத்தவும். - முடிவுகளின் வரிசை முக்கியமில்லை மற்றும் நீங்கள் அதிகபட்ச செயல்திறனை விரும்பும்போது
imap_unordered-ஐப் பயன்படுத்தவும்.
உதாரணம்: கால்பேக்குகளுடன் கூடிய அசிங்க்ரோனஸ் டாஸ்க் சப்மிஷன்
from multiprocessing import Pool, cpu_count
import time
def worker_function(x):
# Simulate a time-consuming task
time.sleep(1)
return x * x
def callback_function(result):
print(f"Result received: {result}")
def error_callback_function(exception):
print(f"An error occurred: {exception}")
if __name__ == '__main__':
num_processes = cpu_count()
with Pool(processes=num_processes) as pool:
for i in range(5):
pool.apply_async(worker_function, args=(i,), callback=callback_function, error_callback=error_callback_function)
# Close the pool and wait for all tasks to complete
pool.close()
pool.join()
print("All tasks completed.")
விளக்கம்:
- ஒரு பணி வெற்றிகரமாக முடிந்ததும் அழைக்கப்படும் ஒரு
callback_function-ஐ நாம் வரையறுக்கிறோம். - ஒரு பணி விதிவிலக்கை எழுப்பினால் அழைக்கப்படும் ஒரு
error_callback_function-ஐ நாம் வரையறுக்கிறோம். - பூலுக்கு பணிகளை அசிங்க்ரோனஸாகச் சமர்ப்பிக்க
pool.apply_async()-ஐப் பயன்படுத்துகிறோம். - பூலுக்கு மேலும் எந்தப் பணிகளும் சமர்ப்பிக்கப்படுவதைத் தடுக்க
pool.close()-ஐ அழைக்கிறோம். - புரோகிராமிலிருந்து வெளியேறும் முன் பூலில் உள்ள அனைத்துப் பணிகளும் முடிவடையும் வரை காத்திருக்க
pool.join()-ஐ அழைக்கிறோம்.
பகிரப்பட்ட நினைவக மேலாண்மை
பிராசஸ் பூல்கள் திறமையான இணைச் செயலாக்கத்தை செயல்படுத்தினாலும், பிராசஸ்களுக்கு இடையில் தரவைப் பகிர்வது ஒரு சவாலாக இருக்கலாம். ஒவ்வொரு பிராசஸுக்கும் அதன் சொந்த நினைவக இடம் உள்ளது, இது மற்ற பிராசஸ்களில் உள்ள தரவை நேரடியாக அணுகுவதைத் தடுக்கிறது. பைத்தானின் multiprocessing மாட்யூல், பிராசஸ்களுக்கு இடையில் பாதுகாப்பான மற்றும் திறமையான தரவுப் பகிர்வுக்கு உதவ பகிரப்பட்ட நினைவகப் பொருள்கள் மற்றும் ஒத்திசைவுப் பொருள்களை வழங்குகிறது.
பகிரப்பட்ட நினைவகப் பொருள்கள்: `Value` மற்றும் `Array`
Value மற்றும் Array கிளாஸ்கள் பல பிராசஸ்களால் அணுகக்கூடிய மற்றும் மாற்றக்கூடிய பகிரப்பட்ட நினைவகப் பொருள்களை உருவாக்க உங்களை அனுமதிக்கின்றன.
Value(typecode_or_type, *args, lock=True): ஒரு குறிப்பிட்ட வகையின் ஒற்றை மதிப்பைக் கொண்டிருக்கும் ஒரு பகிரப்பட்ட நினைவகப் பொருளை உருவாக்குகிறது.typecode_or_typeமதிப்பின் தரவு வகையைக் குறிப்பிடுகிறது (எ.கா., இன்டிஜருக்கு'i', டபிளுக்கு'd',ctypes.c_int,ctypes.c_double).lock=Trueரேஸ் கண்டிஷன்களைத் தடுக்க ஒரு தொடர்புடைய லாக்கை உருவாக்குகிறது.Array(typecode_or_type, sequence, lock=True): ஒரு குறிப்பிட்ட வகையின் மதிப்புகளின் அரேவைக் கொண்டிருக்கும் ஒரு பகிரப்பட்ட நினைவகப் பொருளை உருவாக்குகிறது.typecode_or_typeஅரே உறுப்புகளின் தரவு வகையைக் குறிப்பிடுகிறது (எ.கா., இன்டிஜருக்கு'i', டபிளுக்கு'd',ctypes.c_int,ctypes.c_double).sequenceஎன்பது அரேவுக்கான ஆரம்ப மதிப்புகளின் வரிசையாகும்.lock=Trueரேஸ் கண்டிஷன்களைத் தடுக்க ஒரு தொடர்புடைய லாக்கை உருவாக்குகிறது.
உதாரணம்: பிராசஸ்களுக்கு இடையில் ஒரு மதிப்பைப் பகிர்தல்
from multiprocessing import Process, Value, Lock
import time
def increment_value(shared_value, lock, num_increments):
for _ in range(num_increments):
with lock:
shared_value.value += 1
time.sleep(0.01) # Simulate some work
if __name__ == '__main__':
shared_value = Value('i', 0) # Create a shared integer with initial value 0
lock = Lock() # Create a lock for synchronization
num_processes = 3
num_increments = 100
processes = []
for _ in range(num_processes):
p = Process(target=increment_value, args=(shared_value, lock, num_increments))
processes.append(p)
p.start()
for p in processes:
p.join()
print(f"Final value: {shared_value.value}")
விளக்கம்:
- ஆரம்ப மதிப்பு 0 உடன் இன்டிஜர் (
'i') வகையின் ஒரு பகிரப்பட்டValueபொருளை நாம் உருவாக்குகிறோம். - பகிரப்பட்ட மதிப்புக்கான அணுகலை ஒத்திசைக்க ஒரு
Lockபொருளை நாம் உருவாக்குகிறோம். - பல பிராசஸ்களை உருவாக்குகிறோம், ஒவ்வொன்றும் பகிரப்பட்ட மதிப்பை ஒரு குறிப்பிட்ட எண்ணிக்கையிலான முறை அதிகரிக்கிறது.
increment_valueஃபங்ஷனுக்குள், பகிரப்பட்ட மதிப்பை அணுகுவதற்கு முன் லாக்கைப் பெறவும், பின்னர் அதை விடுவிக்கவும்with lock:ஸ்டேட்மென்டைப் பயன்படுத்துகிறோம். இது ஒரே நேரத்தில் ஒரு பிராசஸ் மட்டுமே பகிரப்பட்ட மதிப்பை அணுகுவதை உறுதி செய்கிறது, ரேஸ் கண்டிஷன்களைத் தடுக்கிறது.- அனைத்து பிராசஸ்களும் முடிந்த பிறகு, பகிரப்பட்ட மாறியின் இறுதி மதிப்பை நாம் அச்சிடுகிறோம். லாக் இல்லாமல், ரேஸ் கண்டிஷன்கள் காரணமாக இறுதி மதிப்பு கணிக்க முடியாததாக இருக்கும்.
உதாரணம்: பிராசஸ்களுக்கு இடையில் ஒரு அரேயைப் பகிர்தல்
from multiprocessing import Process, Array
import random
def fill_array(shared_array):
for i in range(len(shared_array)):
shared_array[i] = random.random()
if __name__ == '__main__':
array_size = 10
shared_array = Array('d', array_size) # Create a shared array of doubles
processes = []
for _ in range(3):
p = Process(target=fill_array, args=(shared_array,))
processes.append(p)
p.start()
for p in processes:
p.join()
print(f"Final array: {list(shared_array)}")
விளக்கம்:
- ஒரு குறிப்பிட்ட அளவுடன் டபிள் (
'd') வகையின் ஒரு பகிரப்பட்டArrayபொருளை நாம் உருவாக்குகிறோம். - பல பிராசஸ்களை உருவாக்குகிறோம், ஒவ்வொன்றும் அரேயை ரேண்டம் எண்களால் நிரப்புகிறது.
- அனைத்து பிராசஸ்களும் முடிந்த பிறகு, பகிரப்பட்ட அரேயின் உள்ளடக்கங்களை நாம் அச்சிடுகிறோம். ஒவ்வொரு பிராசஸாலும் செய்யப்பட்ட மாற்றங்கள் பகிரப்பட்ட அரேயில் பிரதிபலிக்கின்றன என்பதைக் கவனியுங்கள்.
ஒத்திசைவுப் பொருள்கள்: லாக்குகள், செமாஃபோர்கள் மற்றும் கண்டிஷன்கள்
பல பிராசஸ்கள் பகிரப்பட்ட நினைவகத்தை அணுகும்போது, ரேஸ் கண்டிஷன்களைத் தடுக்கவும், தரவு நிலைத்தன்மையை உறுதிப்படுத்தவும் ஒத்திசைவுப் பொருள்களைப் பயன்படுத்துவது அவசியம். multiprocessing மாட்யூல் பல ஒத்திசைவுப் பொருள்களை வழங்குகிறது, அவற்றுள்:
Lock: ஒரு அடிப்படை லாக்கிங் மெக்கானிசம், இது ஒரே நேரத்தில் ஒரு பிராசஸை மட்டுமே லாக்கைப் பெற அனுமதிக்கிறது. பகிரப்பட்ட வளங்களை அணுகும் குறியீட்டின் முக்கியமான பகுதிகளைப் பாதுகாக்கப் பயன்படுகிறது.Semaphore: ஒரு பொதுவான ஒத்திசைவுப் பொருள், இது ஒரு குறிப்பிட்ட எண்ணிக்கையிலான பிராசஸ்களை ஒரே நேரத்தில் ஒரு பகிரப்பட்ட வளத்தை அணுக அனுமதிக்கிறது. வரையறுக்கப்பட்ட திறனுள்ள வளங்களுக்கான அணுகலைக் கட்டுப்படுத்தப் பயன்படுகிறது.Condition: ஒரு குறிப்பிட்ட கண்டிஷன் உண்மையாக மாறும் வரை பிராசஸ்கள் காத்திருக்க அனுமதிக்கும் ஒரு ஒத்திசைவுப் பொருள். பெரும்பாலும் புரொடியூசர்-கன்ஸ்யூமர் சூழ்நிலைகளில் பயன்படுத்தப்படுகிறது.
பகிரப்பட்ட Value பொருள்களுடன் Lock-ஐப் பயன்படுத்துவதற்கான ஒரு உதாரணத்தை நாம் ஏற்கனவே பார்த்தோம். ஒரு Condition-ஐப் பயன்படுத்தி ஒரு எளிமைப்படுத்தப்பட்ட புரொடியூசர்-கன்ஸ்யூமர் சூழ்நிலையை ஆராய்வோம்.
உதாரணம்: கண்டிஷனுடன் கூடிய புரொடியூசர்-கன்ஸ்யூமர்
from multiprocessing import Process, Condition, Queue
import time
import random
def producer(condition, queue):
for i in range(5):
time.sleep(random.random())
condition.acquire()
queue.put(i)
print(f"Produced: {i}")
condition.notify()
condition.release()
def consumer(condition, queue):
for _ in range(5):
condition.acquire()
while queue.empty():
print("Consumer waiting...")
condition.wait()
item = queue.get()
print(f"Consumed: {item}")
condition.release()
if __name__ == '__main__':
condition = Condition()
queue = Queue()
p = Process(target=producer, args=(condition, queue))
c = Process(target=consumer, args=(condition, queue))
p.start()
c.start()
p.join()
c.join()
print("Done.")
விளக்கம்:
- தரவின் இன்டர்-பிராசஸ் கம்யூனிகேஷனுக்கு ஒரு
Queueபயன்படுத்தப்படுகிறது. - புரொடியூசர் மற்றும் கன்ஸ்யூமரை ஒத்திசைக்க ஒரு
Conditionபயன்படுத்தப்படுகிறது. கன்ஸ்யூமர் க்யூவில் தரவு கிடைக்கும் வரை காத்திருக்கிறது, மேலும் தரவு தயாரிக்கப்படும்போது புரொடியூசர் கன்ஸ்யூமருக்குத் தெரிவிக்கிறது. - கண்டிஷனுடன் தொடர்புடைய லாக்கைப் பெறவும் விடுவிக்கவும்
condition.acquire()மற்றும்condition.release()மெத்தடுகள் பயன்படுத்தப்படுகின்றன. condition.wait()மெத்தட் லாக்கை விடுவித்து, ஒரு அறிவிப்புக்காகக் காத்திருக்கிறது.condition.notify()மெத்தட் கண்டிஷன் உண்மையாக இருக்கலாம் என்று காத்திருக்கும் ஒரு த்ரெட் (அல்லது பிராசஸ்) க்குத் தெரிவிக்கிறது.
உலகளாவிய பார்வையாளர்களுக்கான பரிசீலனைகள்
உலகளாவிய பார்வையாளர்களுக்காக மல்டிபிராசசிங் பயன்பாடுகளை உருவாக்கும்போது, வெவ்வேறு சூழல்களில் இணக்கத்தன்மை மற்றும் உகந்த செயல்திறனை உறுதிப்படுத்த பல்வேறு காரணிகளைக் கருத்தில் கொள்வது அவசியம்:
- கேரக்டர் என்கோடிங்: பிராசஸ்களுக்கு இடையில் ஸ்டிரிங்குகளைப் பகிரும்போது கேரக்டர் என்கோடிங்கில் கவனமாக இருங்கள். UTF-8 பொதுவாக ஒரு பாதுகாப்பான மற்றும் பரவலாக ஆதரிக்கப்படும் என்கோடிங் ஆகும். தவறான என்கோடிங் வெவ்வேறு மொழிகளைக் கையாளும் போது சிதைந்த உரை அல்லது பிழைகளுக்கு வழிவகுக்கும்.
- லோகேல் அமைப்புகள்: லோகேல் அமைப்புகள் தேதி மற்றும் நேர வடிவமைப்பு போன்ற சில ஃபங்ஷன்களின் நடத்தையைப் பாதிக்கலாம். லோகேல்-குறிப்பிட்ட செயல்பாடுகளைச் சரியாகக் கையாள
localeமாட்யூலைப் பயன்படுத்தக் கருதுங்கள். - நேர மண்டலங்கள்: நேரம் சார்ந்த தரவைக் கையாளும்போது, நேர மண்டலங்களைப் பற்றி அறிந்திருங்கள் மற்றும் நேர மண்டல மாற்றங்களைச் சரியாகக் கையாள
datetimeமாட்யூலைpytzலைப்ரரியுடன் பயன்படுத்தவும். இது வெவ்வேறு புவியியல் பகுதிகளில் செயல்படும் பயன்பாடுகளுக்கு முக்கியமானது. - வள வரம்புகள்: இயக்க முறைமைகள் நினைவகப் பயன்பாடு அல்லது திறந்த கோப்புகளின் எண்ணிக்கை போன்ற பிராசஸ்கள் மீது வள வரம்புகளை விதிக்கலாம். இந்த வரம்புகளை அறிந்து, அதற்கேற்ப உங்கள் பயன்பாட்டை வடிவமைக்கவும். வெவ்வேறு இயக்க முறைமைகள் மற்றும் ஹோஸ்டிங் சூழல்கள் மாறுபட்ட இயல்புநிலை வரம்புகளைக் கொண்டுள்ளன.
- பிளாட்பார்ம் இணக்கத்தன்மை: பைத்தானின்
multiprocessingமாட்யூல் பிளாட்பார்ம்-சார்பற்றதாக வடிவமைக்கப்பட்டிருந்தாலும், வெவ்வேறு இயக்க முறைமைகளில் (விண்டோஸ், மேக்ஓஎஸ், லினக்ஸ்) நடத்தையில் நுட்பமான வேறுபாடுகள் இருக்கலாம். உங்கள் பயன்பாட்டை அனைத்து இலக்கு பிளாட்பார்ம்களிலும் முழுமையாகச் சோதிக்கவும். எடுத்துக்காட்டாக, பிராசஸ்கள் உருவாக்கப்படும் விதம் வேறுபடலாம் (ஃபோர்க்கிங் எதிராக ஸ்பானிங்). - பிழை கையாளுதல் மற்றும் லாக்கிங்: வெவ்வேறு சூழல்களில் ஏற்படக்கூடிய சிக்கல்களைக் கண்டறிந்து தீர்க்க வலுவான பிழை கையாளுதல் மற்றும் லாக்கிங்கைச் செயல்படுத்தவும். லாக் செய்திகள் தெளிவாகவும், தகவலறிந்ததாகவும், மொழிபெயர்க்கக்கூடியதாகவும் இருக்க வேண்டும். எளிதாக பிழைத்திருத்தம் செய்ய ஒரு மையப்படுத்தப்பட்ட லாக்கிங் அமைப்பைப் பயன்படுத்தக் கருதுங்கள்.
- சர்வதேசமயமாக்கல் (i18n) மற்றும் உள்ளூர்மயமாக்கல் (l10n): உங்கள் பயன்பாட்டில் பயனர் இடைமுகங்கள் அல்லது உரை காட்சிகள் இருந்தால், பல மொழிகள் மற்றும் கலாச்சார விருப்பங்களை ஆதரிக்க சர்வதேசமயமாக்கல் மற்றும் உள்ளூர்மயமாக்கலைக் கருத்தில் கொள்ளுங்கள். இது ஸ்டிரிங்குகளை வெளிப்புறப்படுத்துதல் மற்றும் வெவ்வேறு லோகேல்களுக்கு மொழிபெயர்ப்புகளை வழங்குவதை உள்ளடக்கியிருக்கலாம்.
மல்டிபிராசசிங்கிற்கான சிறந்த நடைமுறைகள்
மல்டிபிராசசிங்கின் நன்மைகளை அதிகரிக்கவும், பொதுவான சிக்கல்களைத் தவிர்க்கவும், இந்தப் சிறந்த நடைமுறைகளைப் பின்பற்றவும்:
- பணிகளைச் சுதந்திரமாக வைத்திருங்கள்: பகிரப்பட்ட நினைவகம் மற்றும் ஒத்திசைவுக்கான தேவையைக் குறைக்க உங்கள் பணிகளை முடிந்தவரை சுதந்திரமாக வடிவமைக்கவும். இது ரேஸ் கண்டிஷன்கள் மற்றும் மோதல்களின் அபாயத்தைக் குறைக்கிறது.
- தரவுப் பரிமாற்றத்தைக் குறைக்கவும்: ஓவர்ஹெட்டைக் குறைக்க பிராசஸ்களுக்கு இடையில் தேவையான தரவை மட்டுமே மாற்றவும். முடிந்தால் பெரிய தரவுக் கட்டமைப்புகளைப் பகிர்வதைத் தவிர்க்கவும். மிகப் பெரிய தரவுத்தொகுப்புகளுக்கு ஜீரோ-காப்பி ஷேரிங் அல்லது மெமரி மேப்பிங் போன்ற நுட்பங்களைப் பயன்படுத்தக் கருதுங்கள்.
- லாக்குகளை குறைவாகப் பயன்படுத்துங்கள்: லாக்குகளை அதிகமாகப் பயன்படுத்துவது செயல்திறன் சிக்கல்களுக்கு வழிவகுக்கும். குறியீட்டின் முக்கியமான பகுதிகளைப் பாதுகாக்கத் தேவைப்படும்போது மட்டுமே லாக்குகளைப் பயன்படுத்தவும். பொருத்தமானால், செமாஃபோர்கள் அல்லது கண்டிஷன்கள் போன்ற மாற்று ஒத்திசைவுப் பொருள்களைப் பயன்படுத்தக் கருதுங்கள்.
- டெட்லாக்குகளைத் தவிர்க்கவும்: இரண்டு அல்லது அதற்கு மேற்பட்ட பிராசஸ்கள் காலவரையின்றித் தடுக்கப்பட்டு, வளங்களை விடுவிக்க ஒருவருக்கொருவர் காத்திருக்கும்போது ஏற்படக்கூடிய டெட்லாக்குகளைத் தவிர்க்கக் கவனமாக இருங்கள். டெட்லாக்குகளைத் தடுக்க ஒரு நிலையான லாக்கிங் வரிசையைப் பயன்படுத்தவும்.
- விதிவிலக்குகளைச் சரியாகக் கையாளவும்: வொர்க்கர் பிராசஸ்களில் விதிவிலக்குகளைக் கையாண்டு, அவை செயலிழந்து முழுப் பயன்பாட்டையும் செயலிழக்கச் செய்வதைத் தடுக்கவும். விதிவிலக்குகளைப் பிடிக்கவும், அவற்றை முறையாக லாக் செய்யவும் try-except பிளாக்குகளைப் பயன்படுத்தவும்.
- வளப் பயன்பாட்டைக் கண்காணிக்கவும்: சாத்தியமான சிக்கல்கள் அல்லது செயல்திறன் சிக்கல்களைக் கண்டறிய உங்கள் மல்டிபிராசசிங் பயன்பாட்டின் வளப் பயன்பாட்டைக் கண்காணிக்கவும். CPU பயன்பாடு, நினைவகப் பயன்பாடு மற்றும் I/O செயல்பாட்டைக் கண்காணிக்க
psutilபோன்ற கருவிகளைப் பயன்படுத்தவும். - ஒரு டாஸ்க் க்யூவைப் பயன்படுத்தக் கருதுங்கள்: மிகவும் சிக்கலான சூழ்நிலைகளுக்கு, பணிகளை நிர்வகிக்கவும், அவற்றை பல பிராசஸ்கள் அல்லது பல இயந்திரங்களில் விநியோகிக்கவும் ஒரு டாஸ்க் க்யூவைப் (எ.கா., செலரி, ரெடிஸ் க்யூ) பயன்படுத்தக் கருதுங்கள். டாஸ்க் க்யூக்கள் பணி முன்னுரிமை, மறு முயற்சி வழிமுறைகள் மற்றும் கண்காணிப்பு போன்ற அம்சங்களை வழங்குகின்றன.
- உங்கள் குறியீட்டை புரோஃபைல் செய்யவும்: உங்கள் குறியீட்டின் அதிக நேரம் எடுக்கும் பகுதிகளைக் கண்டறிய ஒரு புரோஃபைலரைப் பயன்படுத்தவும், மேலும் உங்கள் மேம்படுத்தல் முயற்சிகளை அந்தப் பகுதிகளில் கவனம் செலுத்தவும். பைத்தான்
cProfileமற்றும்line_profilerபோன்ற பல புரோஃபைலிங் கருவிகளை வழங்குகிறது. - முழுமையாகச் சோதிக்கவும்: உங்கள் மல்டிபிராசசிங் பயன்பாடு சரியாக மற்றும் திறமையாகச் செயல்படுகிறதா என்பதை உறுதிப்படுத்த முழுமையாகச் சோதிக்கவும். தனிப்பட்ட கூறுகளின் சரியானத்தன்மையைச் சரிபார்க்க யூனிட் டெஸ்ட்களையும், வெவ்வேறு பிராசஸ்களுக்கு இடையிலான தொடர்பைச் சரிபார்க்க இன்டக்ரேஷன் டெஸ்ட்களையும் பயன்படுத்தவும்.
- உங்கள் குறியீட்டை ஆவணப்படுத்தவும்: ஒவ்வொரு பிராசஸின் நோக்கம், பயன்படுத்தப்படும் பகிரப்பட்ட நினைவகப் பொருள்கள் மற்றும் பயன்படுத்தப்படும் ஒத்திசைவு வழிமுறைகள் உட்பட உங்கள் குறியீட்டைத் தெளிவாக ஆவணப்படுத்தவும். இது மற்றவர்கள் உங்கள் குறியீட்டைப் புரிந்துகொள்வதையும் பராமரிப்பதையும் எளிதாக்கும்.
மேம்பட்ட நுட்பங்கள் மற்றும் மாற்று வழிகள்
பிராசஸ் பூல்கள் மற்றும் பகிரப்பட்ட நினைவகத்தின் அடிப்படைகளுக்கு அப்பால், மிகவும் சிக்கலான மல்டிபிராசசிங் சூழ்நிலைகளுக்குக் கருத்தில் கொள்ள பல மேம்பட்ட நுட்பங்கள் மற்றும் மாற்று அணுகுமுறைகள் உள்ளன:
- ZeroMQ: இன்டர்-பிராசஸ் கம்யூனிகேஷனுக்குப் பயன்படுத்தக்கூடிய ஒரு உயர் செயல்திறன் கொண்ட அசிங்க்ரோனஸ் மெசேஜிங் லைப்ரரி. ZeroMQ பப்ளிஷ்-சப்ஸ்கிரைப், ரிக்வெஸ்ட்-ரிப்ளை மற்றும் புஷ்-புல் போன்ற பல்வேறு மெசேஜிங் பேட்டர்ன்களை வழங்குகிறது.
- Redis: பகிரப்பட்ட நினைவகம் மற்றும் இன்டர்-பிராசஸ் கம்யூனிகேஷனுக்குப் பயன்படுத்தக்கூடிய ஒரு இன்-மெமரி டேட்டா ஸ்ட்ரக்சர் ஸ்டோர். Redis பப்/சப், டிரான்ஸாக்ஷன்ஸ் மற்றும் ஸ்கிரிப்டிங் போன்ற அம்சங்களை வழங்குகிறது.
- Dask: பெரிய தரவுத்தொகுப்புகளில் கணக்கீடுகளை இணைச் செயலாக்கம் செய்ய உயர்-நிலை இடைமுகத்தை வழங்கும் ஒரு இணை கணினி லைப்ரரி. Dask-ஐ பிராசஸ் பூல்கள் அல்லது டிஸ்ட்ரிபியூட்டட் கிளஸ்டர்களுடன் பயன்படுத்தலாம்.
- Ray: AI மற்றும் பைத்தான் பயன்பாடுகளை உருவாக்குவதையும் அளவிடுவதையும் எளிதாக்கும் ஒரு டிஸ்ட்ரிபியூட்டட் எக்ஸிகியூஷன் ஃபிரேம்வொர்க். Ray ரிமோட் ஃபங்ஷன் கால்கள், டிஸ்ட்ரிபியூட்டட் ஆக்டர்கள் மற்றும் ஆட்டோமேட்டிக் டேட்டா மேனேஜ்மென்ட் போன்ற அம்சங்களை வழங்குகிறது.
- MPI (Message Passing Interface): இன்டர்-பிராசஸ் கம்யூனிகேஷனுக்கான ஒரு ஸ்டாண்டர்டு, பொதுவாக அறிவியல் கணினியில் பயன்படுத்தப்படுகிறது. பைத்தானில்
mpi4pyபோன்ற MPI-க்கான பைண்டிங்குகள் உள்ளன. - பகிரப்பட்ட நினைவகக் கோப்புகள் (mmap): மெமரி மேப்பிங் ஒரு கோப்பை நினைவகத்தில் மேப் செய்ய உங்களை அனுமதிக்கிறது, இதனால் பல பிராசஸ்கள் ஒரே கோப்புத் தரவை நேரடியாக அணுக முடியும். இது பாரம்பரிய கோப்பு I/O மூலம் தரவைப் படிப்பதையும் எழுதுவதையும் விட மிகவும் திறமையானதாக இருக்கும். பைத்தானில் உள்ள
mmapமாட்யூல் மெமரி மேப்பிங்கிற்கான ஆதரவை வழங்குகிறது. - பிற மொழிகளில் பிராசஸ்-சார்ந்த மற்றும் த்ரெட்-சார்ந்த கன்கர்ரன்சி: இந்த வழிகாட்டி பைத்தானில் கவனம் செலுத்தினாலும், பிற மொழிகளில் உள்ள கன்கர்ரன்சி மாடல்களைப் புரிந்துகொள்வது மதிப்புமிக்க நுண்ணறிவுகளை வழங்க முடியும். எடுத்துக்காட்டாக, Go கன்கர்ரன்சிக்கு கோரூட்டின்கள் (இலகுரக த்ரெட்கள்) மற்றும் சேனல்களைப் பயன்படுத்துகிறது, அதே நேரத்தில் ஜாவா த்ரெட்கள் மற்றும் பிராசஸ்-சார்ந்த இணைச் செயலாக்கம் இரண்டையும் வழங்குகிறது.
முடிவுரை
பைத்தானின் multiprocessing மாட்யூல், CPU-சார்ந்த பணிகளை இணைச் செயலாக்கம் செய்வதற்கும், பிராசஸ்களுக்கு இடையில் பகிரப்பட்ட நினைவகத்தை நிர்வகிப்பதற்கும் ஒரு சக்திவாய்ந்த கருவிகளின் தொகுப்பை வழங்குகிறது. பிராசஸ் பூல்கள், பகிரப்பட்ட நினைவகப் பொருள்கள் மற்றும் ஒத்திசைவுப் பொருள்கள் ஆகியவற்றின் கருத்துக்களைப் புரிந்துகொள்வதன் மூலம், உங்கள் மல்டி-கோர் பிராசசர்களின் முழு திறனையும் நீங்கள் வெளிக்கொணரலாம் மற்றும் உங்கள் பைத்தான் பயன்பாடுகளின் செயல்திறனை கணிசமாக மேம்படுத்தலாம்.
மல்டிபிராசசிங்கில் உள்ள வர்த்தகப் பரிமாற்றங்களை, அதாவது இன்டர்-பிராசஸ் கம்யூனிகேஷனின் ஓவர்ஹெட் மற்றும் பகிரப்பட்ட நினைவகத்தை நிர்வகிப்பதன் சிக்கலான தன்மை போன்றவற்றைக் கவனமாகக் கருத்தில் கொள்ள நினைவில் கொள்ளுங்கள். சிறந்த நடைமுறைகளைப் பின்பற்றுவதன் மூலமும், உங்கள் குறிப்பிட்ட தேவைகளுக்குப் பொருத்தமான நுட்பங்களைத் தேர்ந்தெடுப்பதன் மூலமும், உலகளாவிய பார்வையாளர்களுக்காக திறமையான மற்றும் அளவிடக்கூடிய மல்டிபிராசசிங் பயன்பாடுகளை நீங்கள் உருவாக்கலாம். முழுமையான சோதனை மற்றும் வலுவான பிழை கையாளுதல் ஆகியவை மிக முக்கியமானவை, குறிப்பாக உலகெங்கிலும் உள்ள பல்வேறு சூழல்களில் நம்பகத்தன்மையுடன் இயங்க வேண்டிய பயன்பாடுகளைப் பயன்படுத்தும்போது.